package modify

import (
	"context"
	"time"

	v1 "code.byted.org/bytertc/whiteboard_server/biz/api/pb/v1"
	"code.byted.org/bytertc/whiteboard_server/biz/pkg/biz_error"
	"code.byted.org/bytertc/whiteboard_server/biz/service/command"
	"code.byted.org/bytertc/whiteboard_server/biz/service/command/base"
	"code.byted.org/bytertc/whiteboard_server/biz/service/object"
	"code.byted.org/gopkg/logs/v2/log"
	"github.com/pkg/errors"
)

func NewCreateBoardCommand(ctx context.Context, cmd *base.Command, boardId int32, boardName string, initialPages []*v1.PageInfo, pptInfo *v1.PptInfo, taskID *string, totalSize *int32) *createBoardCommand {
	return &createBoardCommand{
		Command:      *cmd,
		boardId:      boardId,
		initialPages: initialPages,
		boardName:    boardName,
		pptInfo:      pptInfo,
		taskID:       taskID,
		totalSize:    totalSize,
	}
}

type createBoardCommand struct {
	base.Command
	boardId      int32
	initialPages []*v1.PageInfo
	boardName    string
	pptInfo      *v1.PptInfo
	taskID       *string
	totalSize    *int32
}

func (c *createBoardCommand) GetBoardId() int32 {
	return c.boardId
}

func (c *createBoardCommand) Execute(ctx context.Context) []command.Result {
	if c.initialPages == nil {
		c.initialPages = []*v1.PageInfo{{
			PageId: "wb_default",
		}}
	}
	curStep := int32(0)
	initBoard := &v1.BoardInfo{
		BoardId:       c.boardId,
		Pages:         c.initialPages,
		CurrentPageId: c.initialPages[0].PageId,
		BoardName:     &c.boardName,
		CurrentStep:   &curStep,
		PptInfo:       c.pptInfo,
	}
	err := c.Repo.CreateBoard(ctx, c, initBoard, c.initialPages)
	return c.generateResponse(ctx, err)
}

func (c *createBoardCommand) generateResponse(ctx context.Context, err error) []command.Result {
	resp := &v1.CreateBoardResponse{
		Status:    v1.ResponseStatus_Succeed,
		BoardId:   c.boardId,
		PptConfig: c.pptInfo,
		TaskId:    c.taskID,
		TotalSize: c.totalSize,
	}
	unicastRes := &base.Result{
		Msg:         resp,
		IsBroadcast: false,
		CommandType: v1.Command_kCreateBoard,
		Error:       nil,
	}
	if errors.Is(err, biz_error.Conflict) {
		resp.Status = v1.ResponseStatus_Conflict
		log.V1.CtxInfo(ctx, "%+v", err)
		return []command.Result{unicastRes}
	} else if err != nil {
		resp.Status = v1.ResponseStatus_Error
		unicastRes.Error = err
		return []command.Result{unicastRes}
	}
	controlCount := make(map[string]int32)
	for _, page := range c.initialPages {
		controlCount[page.PageId] = object.InitialActionCount
	}
	creatTime := uint64(time.Now().Unix())
	curStep := int32(0)
	broadcastRes := &base.Result{
		Msg: &v1.CreateBoardMessage{
			Board: &v1.BoardInfo{
				BoardId:         c.boardId,
				Pages:           c.initialPages,
				CurrentPageId:   c.initialPages[0].PageId,
				CurrentStep:     &curStep,
				ControlCount:    controlCount,
				BoardName:       &c.boardName,
				CreateTimestamp: &creatTime,
				PptInfo:         c.pptInfo,
			},
			PptConfig: c.pptInfo,
			TaskId:    c.taskID,
			TotalSize: c.totalSize,
		},
		IsBroadcast: true,
		CommandType: v1.Command_kCreateBoardMessage,
		Error:       nil,
	}
	return []command.Result{unicastRes, broadcastRes}
}
